package logica.util;

import java.util.Hashtable;
import java.util.StringTokenizer;
import java.util.regex.Matcher;

public class TratamientoCadena {

    /*
     * Este vector contiene los caracteres que se van a limpiar de un texto, por un espacio en blanco
     * En el caso de las letras acentuadas, se le quitan los acentos a las mismas
     */
    private static String[][] caracteresLimpiar = {
        {",", " "}, {".", " "}, {";", " "}, {"'", ""},
        {"(", " "}, {")", " "}, {"[", " "}, {"]", " "},
        {"-", " "}, {"+", " "}, {"¡", " "}, {"!", " "},
        {"á", "a"}, {"é", "e"}, {"í", "i"}, {"ó", "o"}, {"ú", "u"},
        {":", " "}, {"\"", " "},
        {"%", " "}, {"$", " "},
        {"¿", " "}, {"?", " "},
        {"0", " "}, {"1", " "}, {"2", " "}, {"3", " "}, {"4", " "},
        {"5", " "}, {"6", " "}, {"7", " "}, {"8", " "}, {"9", " "},
        {"&#", " "}, {"�", " "},
        {"<i>", " "}, {"</i>", " "}, {"<p>", " "}, {"</p>", " "},
        {"</b>", " "}, {"<b>", " "},
        {"°", " "}, {"&", " "}, {"ª", " "}
    };

    /*
     * Este vector, contiene los caracteres que se van a estandarizar, de un texto en cuestión
     */
    private static String[][] caracteresEstandarizar = {
        {"Ã¡", "á"}, {"Ã©", "é"}, {"Ã", "í"},
        {"Ã", "í"}, {"Ã³", "ó"}, {"Ãº", "ú"},
        {"í³", "ó"}, {"í±", "ñ"}, {"í³", "ó"},
        {"íº", "ú"}, {"&quot;", "\""}, {"&iacute;", "í"},
        {"&oacute;", "ó"}, {"&oecute;", "é"}, {"&eacute;", "é"},
        {"&aacute;", "á"}, {"&oucute;", "ú"}, {"&oucute;", "ú"},
        {"&uacute;", "ú"}, {"&ntilde;", "ñ"}
    };

    /*
     *
     */
    private static Hashtable<String, String> hashPalabrasVacias = new Hashtable<String, String>();

    /*
     * Este vector, contiene las palabras vacías o Stop Words, que se van a descartar
     * a la hora de la indexación.
     * Se incluye: preposiciones , adverbios, artículos , conjunciones, distributivos, indefinidos,
     * interjecciones, numerales, posesivos, pronombres
     */
    private static String palabrasVacias[] = {
        "a", "al", "asi", "aun", "aca", "ademas", "ahi", "ahora", "alguien", "alguna", "algunas", "alguno", "algunos", "alla", "ambos", "ambas", "antes", "aquel", "aquellos", "aquella", "aquellas", "aqui", "ago", "ante", "alli", "aunque", "ay", "aupa", "adios",
        "bien", "bueno", "bajo",
        "cabe", "causa", "cierta", "cierto", "ciertos", "cinco", "con", "como", "consecuentemente", "constante", "constantemente", "contra", "com", "cuan", "cuanto", "cuanta", "cuantas", "cuantos", "cualquiera", "cuatro", "cual", "cerca", "cuando", "cortesmente", "casi", "conque", "cada", "cualquier", "cielos", "cuyo",
        "dar", "de", "del", "donde", "deprisa", "desde", "despacio", "despues", "dificil", "dio", "dos", "durante", "demasiado", "doble",
        "el", "ellos", "es", "en", "este", "esta", "esto", "estas", "estos", "eso", "esa", "esos", "esas", "ese", "ellas", "ella", "era", "ello", "entre", "efectivamente", "exclusive", "excepto", "e", "ea",
        "facil", "facilmente", "frecuentemente", "fue",
        "ha", "habitual", "habitualmente", "hacia", "halla", "has", "hasta", "hay", "hoy", "hola",
        "ir", "instante", "instantes", "incluso", "inclusive",
        "jamas",
        "la", "las", "le", "les", "lo", "los", "luego",
        "mal", "mas", "me", "mediante", "medio", "menos", "mes", "mitad", "mi", "mios", "mientras", "mis", "misma", "mismo", "mismos", "modo", "momento", "momentos", "mucha", "muchas", "mucho", "muy",
        "n°", "nada", "nadie", "ni", "ningun", "ninguno", "no", "nos", "nosotros", "nuestra", "nuestro", "nuestros", "nunca", "nosotras",
        "otro", "otra", "otros", "otras", "obstante", "ojala", "o", "oh", "os",
        "para", "pese", "pero", "porque", "poca", "pocas", "poco", "pocos", "por", "pleno", "proposito", "pronto", "pro", "posiblemente", "primeramente", "pues", "primero",
        "que", "quien", "quizas", "quiza", "quienes",
        "respecto", "respectivamente", "referente", "recien",
        "segun", "seis", "se", "ser", "si", "sin", "solamente", "sobre", "son", "suya", "suyas", "suyo", "suyos", "su", "sus", "salvo", "sino", "sendos",
        "tantos", "tanto", "tanta", "tantas", "tan", "tambien", "tal", "te", "todo", "toda", "todos", "todas", "tu", "tuya", "tuyas", "tuyo", "tuyos", "tras", "traves", "tres", "ti",
        "uno", "unos", "unas", "un", "una", "usted", "ustedes", "u", "uy",
        "va", "van", "varios", "varias", "ve", "venir", "venimos", "vino", "vos", "via", "venga", "vosotros", "vosotras",
        "y", "ya", "yo"
    };

    /**
     * Esta función se utiliza para estandarizar los caracteres del texto, correspondiente al título de una noticia
     * @param tituloDocumento - un String, que representa el texto del título de la noticia original
     * @return tituloDocumento - un String, que representa el texto del título de la noticia, con los caracteres estandarizados
     */
    public static String tratarTituloDocumento(String tituloDocumento) {
        tituloDocumento = estandarizarTexto(tituloDocumento);
        //tituloDocumento = limpiarTexto(tituloDocumento);
        return tituloDocumento;
    }

    /**
     * Esta función se utiliza para estandarizar los caracteres del texto, correspondiente a la descripción de una noticia
     * y además, se eliminan las etiquetas web, que se puedan haber guardado junto con la noticia.
     * @param descripcionDocumento - un String, que representa el texto de la descripción de la noticia original
     * @return tituloDocumento - un String, que representa el texto de la descripción de la noticia, con los caracteres estandarizados y sin etiquetas web
     */
    public static String tratarDescripcionDocumento(String descripcionDocumento) {
        //descripcionDocumento = TratamientoCadena.eliminarURL(descripcionDocumento); 
        descripcionDocumento = TratamientoCadena.eliminarEtiquetasWeb(descripcionDocumento);
        descripcionDocumento = TratamientoCadena.estandarizarTexto(descripcionDocumento);
        return descripcionDocumento;
    }

    /**
     * Esta función se utiliza para limpiar el texto de una noticia, para poder realizar la indexación
     * correspondiente. Para ello, se pasa a minúscula todo el texto, se eliminan las palabras vacías,
     * y se limpian los caracteres especiales
     * @param textoIndexacion - un String, que representa el texto del título y la descripción de la noticia
     * @return textoIndexacion - un String, que representa el texto del título y la descripción limpio
     */
    public static String tratarTextoIndexacion(String textoIndexacion) {
        textoIndexacion = textoIndexacion.toLowerCase();
        textoIndexacion = TratamientoCadena.eliminarPalabrasVacias(textoIndexacion);
        textoIndexacion = TratamientoCadena.limpiarTexto(textoIndexacion);
        return textoIndexacion;
    }

    /**
     * Esta función se utiliza para limpiar el texto de una noticia, para poder realizar la indexación
     * correspondiente. Para ello, se pasa a minúscula todo el texto, se eliminan las palabras vacías,
     * y se limpian los caracteres especiales
     * @param textoBusqueda - un String, que representa el texto del título y la descripción de la noticia
     * @return textoBusqueda - un String, que representa el texto del título y la descripción limpio
     */
    public static String tratarTextoBusqueda(String textoBusqueda) {
        textoBusqueda = textoBusqueda.toLowerCase();
        textoBusqueda = TratamientoCadena.eliminarPalabrasVacias(textoBusqueda);
        textoBusqueda = TratamientoCadena.limpiarTexto(textoBusqueda);
        return textoBusqueda;
    }

    /*
    private static String eliminarURL(String texto) {
    Matcher matcherTagURL = ER.obtenerMatcher(ER.TAG_HTML_A, texto);
    boolean esTagURL = matcherTagURL.find();
    if (esTagURL) {
    texto = matcherTagURL.group(1) + " " + matcherTagURL.group(2) + " " + matcherTagURL.group(3);
    }
    return texto;
    }
     */

    /*
     * Esta función se utiliza, para eliminar etiquetas web, que se puedan haber filtrado
     * en un texto. En este caso, se eliminan las etiquetas A, H, I, P, B.
     * @param texto - un string, que representa un texto,
     * @return texto - un string,
     */
    private static String eliminarEtiquetasWeb(String texto) {
        Matcher matcherTagURL = ER.obtenerMatcher(ER.TAG_HTML_A_3, texto);
        boolean esTagURL = matcherTagURL.find();

        if (esTagURL) {
            String aux1, aux2, aux8;
            //aca se levanta todo el texto que detecta la ER - esta a modo de ayuda
            aux1 = matcherTagURL.group();
            //aca se levanta el 1er grupo que detecta dentro del texto, la ER
            aux2 = matcherTagURL.group(1);
            //aca reemplazo todo el texto que levanto la ER matcherTagURL.group(), por lo del grupo 1, matcherTagURL.group(1)
            aux8 = matcherTagURL.replaceAll(matcherTagURL.group(1));
            texto = aux8;
        }

        matcherTagURL = ER.obtenerMatcher(ER.TAG_HTML_H, texto);
        esTagURL = matcherTagURL.find();
        if (esTagURL) {
            String aux1, aux2, aux8;
            //aca se levanta todo el texto que detecta la ER - esta a modo de ayuda
            aux1 = matcherTagURL.group();
            //aca se levanta el 1er grupo que detecta dentro del texto, la ER
            aux2 = matcherTagURL.group(1);
            //aca reemplazo todo el texto que levanto la ER matcherTagURL.group(), por lo del grupo 1, matcherTagURL.group(1)
            aux8 = matcherTagURL.replaceAll(matcherTagURL.group(1));
            texto = aux8;
        }

        matcherTagURL = ER.obtenerMatcher(ER.TAG_HTML_I, texto);
        esTagURL = matcherTagURL.find();
        if (esTagURL) {
            String aux1, aux2, aux8;
            //aca se levanta todo el texto que detecta la ER - esta a modo de ayuda
            aux1 = matcherTagURL.group();
            //aca se levanta el 1er grupo que detecta dentro del texto, la ER
            aux2 = matcherTagURL.group(1);
            //aca reemplazo todo el texto que levanto la ER matcherTagURL.group(), por lo del grupo 1, matcherTagURL.group(1)
            aux8 = matcherTagURL.replaceAll(matcherTagURL.group(1));
            texto = aux8;
        }

        matcherTagURL = ER.obtenerMatcher(ER.TAG_HTML_P, texto);
        esTagURL = matcherTagURL.find();
        if (esTagURL) {
            String aux1, aux2, aux8;
            //aca se levanta todo el texto que detecta la ER - esta a modo de ayuda
            aux1 = matcherTagURL.group();
            //aca se levanta el 1er grupo que detecta dentro del texto, la ER
            aux2 = matcherTagURL.group(1);
            //aca reemplazo todo el texto que levanto la ER matcherTagURL.group(), por lo del grupo 1, matcherTagURL.group(1)
            aux8 = matcherTagURL.replaceAll(matcherTagURL.group(1));
            texto = aux8;
        }

        matcherTagURL = ER.obtenerMatcher(ER.TAG_HTML_B, texto);
        esTagURL = matcherTagURL.find();
        if (esTagURL) {
            String aux1, aux2, aux8;
            //aca se levanta todo el texto que detecta la ER - esta a modo de ayuda
            aux1 = matcherTagURL.group();
            //aca se levanta el 1er grupo que detecta dentro del texto, la ER
            aux2 = matcherTagURL.group(1);
            //aca reemplazo todo el texto que levanto la ER matcherTagURL.group(), por lo del grupo 1, matcherTagURL.group(1)
            aux8 = matcherTagURL.replaceAll(matcherTagURL.group(1));
            texto = aux8;
        }

        return texto;
    }

    /*
     * Esta función, para una cadena, recorre el vector de caracteres a estandarizar, y la reemplaza
     * por el correspondiente valor, en caso de encontrarse la misma
     * @param cadena - un string, que representa una cadena,
     * @return cadena - un string,
     */
    private static String estandarizarTexto(String cadena) {
        for (int i = 0; i < caracteresEstandarizar.length; i++) {
            cadena = cadena.replace(caracteresEstandarizar[i][0], caracteresEstandarizar[i][1]);
        }
        return cadena;
    }

    /*
     * Esta función, para una cadena, recorre el vector de caracteres a limpiar, y la reemplaza
     * por el correspondiente valor, en caso de encontrarse la misma
     * @param cadena - un string, que representa una cadena,
     * @return cadena - un string,
     */
    public static String limpiarTexto(String cadena) {
        for (int i = 0; i < caracteresLimpiar.length; i++) {
            cadena = cadena.replace(caracteresLimpiar[i][0], caracteresLimpiar[i][1]);
        }
        cadena = cadena.trim();//limpia caracteres en blanco
        return cadena;
    }

    /*
     * Esta función determina el tamaño de una palabra, y si es de uno, la marca como palabra vacía
     * @param cadena - un string, que representa una palabra,
     * @return cadena - un string,
     */
    public static boolean esPalabraVacia(String palabra) {
        boolean esPalabraVacia = false;

        //si la palabra tiene longitud igual a uno retorna true
        if (palabra.length() == 1) {
            esPalabraVacia = true;
        } else {
            if (hashPalabrasVacias.containsKey(palabra)) {
                esPalabraVacia = true;
            }
        }

        return esPalabraVacia;
    }

    /*
     * Esta función se encarga de quitar de un texto, las palabras stop Words,
     * Estas se obtienen del vector palabrasVacias y retorna el nuevo texto, sin las palabras vacias
     * @param texto - un string, que representa un texto,
     * @return texto - un string,
     */
    public static String eliminarPalabrasVacias(String texto) {
        String nuevoTexto = "";
        StringTokenizer palabras = new StringTokenizer(texto);//divide el texto en palabras

        while (palabras.hasMoreElements()) {
            String palabra = palabras.nextElement().toString();
            if (!TratamientoCadena.esPalabraVacia(palabra)) {
                //TODO Ver de usar StringBuilder
                nuevoTexto += palabra + " ";
            }
        }

        return nuevoTexto;
    }

    /*
     * Esta función recorre el vector de palabras vacías y le realiza un hash
     */
    static {
        for (int i = 0; i < palabrasVacias.length; i++) {
            hashPalabrasVacias.put(palabrasVacias[i], "");
        }
    }
}
